Skip to content

Comments

fix: debug_traceTransaction default param#9788

Merged
macfarla merged 10 commits intohyperledger:mainfrom
macfarla:debug-trace-tx-empty-options
Feb 24, 2026
Merged

fix: debug_traceTransaction default param#9788
macfarla merged 10 commits intohyperledger:mainfrom
macfarla:debug-trace-tx-empty-options

Conversation

@macfarla
Copy link
Contributor

@macfarla macfarla commented Feb 11, 2026

PR description

When reviewing docs PR 1909, claude picked up an inconsistency with default parameters when no params are supplied vs empty {} params - as described in #9787

Docs still needs correcting here to say disableMemory is true by default (all other booleans default to false) https://besu.hyperledger.org/public-networks/reference/api#debug_tracetransaction

Fixed Issue(s)

fixes #9787

Thanks for sending a pull request! Have you done the following?

  • Checked out our contribution guidelines?
  • Considered documentation and added the doc-change-required label to this PR if updates are required.
  • Considered the changelog and included an update if required.
  • For database changes (e.g. KeyValueSegmentIdentifier) considered compatibility and performed forwards and backwards compatibility tests

Locally, you can run these tests to catch failures early:

  • spotless: ./gradlew spotlessApply
  • unit tests: ./gradlew build
  • acceptance tests: ./gradlew acceptanceTest
  • integration tests: ./gradlew integrationTest
  • reference tests: ./gradlew ethereum:referenceTests:referenceTests
  • hive tests: Engine or other RPCs modified?

Signed-off-by: Sally MacFarlane <macfarla.github@gmail.com>
Signed-off-by: Sally MacFarlane <macfarla.github@gmail.com>
Signed-off-by: Sally MacFarlane <macfarla.github@gmail.com>
@macfarla macfarla marked this pull request as draft February 12, 2026 00:51
…ue, matching the documented API behavior

Signed-off-by: Sally MacFarlane <macfarla.github@gmail.com>
Signed-off-by: Sally MacFarlane <macfarla.github@gmail.com>
@macfarla macfarla marked this pull request as ready for review February 12, 2026 05:42
usmansaleem
usmansaleem previously approved these changes Feb 12, 2026
Copy link
Member

@usmansaleem usmansaleem left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@macfarla macfarla marked this pull request as draft February 12, 2026 23:28
Signed-off-by: Sally MacFarlane <macfarla.github@gmail.com>
@macfarla macfarla requested a review from usmansaleem February 12, 2026 23:59
@macfarla macfarla dismissed usmansaleem’s stale review February 13, 2026 00:00

I have pushed more changes

Signed-off-by: Sally MacFarlane <macfarla.github@gmail.com>
@macfarla
Copy link
Contributor Author

@lu-pinto can you review this one - the default param behavior is currently inconsistent between RPCs - this came up from looking at a docs PR hyperledger/besu-docs#1909 - in one spot we say the trace flags are all false by default but looking at the code that's not the case, and actually you currently get different behavior between passing no options and empty {} options

@macfarla macfarla marked this pull request as ready for review February 13, 2026 01:26
Copy link
Member

@lu-pinto lu-pinto left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, I think the default behavior for Geth is also to not show memory if not enabled. Make sense to align cases with empty params with no params at all

@macfarla macfarla assigned macfarla and unassigned lu-pinto Feb 23, 2026
Signed-off-by: Sally MacFarlane <macfarla.github@gmail.com>
Copilot AI review requested due to automatic review settings February 24, 2026 02:33
@macfarla macfarla enabled auto-merge (squash) February 24, 2026 02:35
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes debug_traceTransaction option-default behavior so debug_traceTransaction(hash) and debug_traceTransaction(hash,{}) behave consistently, and adjusts memory tracing defaults for non-opcode tracers.

Changes:

  • Update TransactionTraceParams#traceOptions() to only override tracer defaults when a user explicitly supplies disable* fields, and to enable memory by default for non-opcode tracers unless explicitly disabled.
  • Add unit tests covering {} vs defaults and callTracer memory-default behavior.
  • Update JSON-RPC trace fixtures to reflect the new effective defaults (notably memory capture changes).

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/TransactionTraceParams.java Adjusts how trace options are derived so explicit vs missing params behave consistently; enables memory for non-opcode tracers by default.
ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/TransactionTraceParamsTest.java Adds coverage for {} matching defaults, opcode tracer defaults, and callTracer memory behavior.
ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/jsonrpc/debug/trace-transaction/debug_traceTransaction_disableStorage.json Updates expected trace output with memory fields omitted per new defaults.
ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/jsonrpc/debug/trace-transaction/debug_traceTransaction_disableStack.json Updates expected trace output with memory fields omitted per new defaults.
ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/jsonrpc/debug/trace-call/debug_traceCall_stateOverride.json Updates expected trace output with memory fields omitted per new defaults.
ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/jsonrpc/debug/trace-call/debug_traceCall_disableStorage.json Updates expected trace output with memory fields omitted per new defaults.
ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/jsonrpc/debug/trace-call/debug_traceCall_disableStack.json Updates expected trace output with memory fields omitted per new defaults.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +31 to +38
// Passing {} should be equivalent to passing no options at all.
// All disable* fields default to false, so all tracing is enabled by default.
final OpCodeTracerConfig defaultConfig = TraceOptions.DEFAULT.opCodeTracerConfig();

// Parse an empty JSON options object — simulates debug_traceTransaction(hash, {})
final TransactionTraceParams emptyParams = MAPPER.readValue("{}", TransactionTraceParams.class);
final OpCodeTracerConfig emptyParamsConfig = emptyParams.traceOptions().opCodeTracerConfig();

Copy link

Copilot AI Feb 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment about defaults is inaccurate/misleading: TraceOptions.DEFAULT has traceMemory() disabled by default (and per PR description, disableMemory is effectively true by default when omitted). Consider updating the comment to reflect that {} should match TraceOptions.DEFAULT, where memory tracing may still be off by default.

Suggested change
// Passing {} should be equivalent to passing no options at all.
// All disable* fields default to false, so all tracing is enabled by default.
final OpCodeTracerConfig defaultConfig = TraceOptions.DEFAULT.opCodeTracerConfig();
// Parse an empty JSON options object — simulates debug_traceTransaction(hash, {})
final TransactionTraceParams emptyParams = MAPPER.readValue("{}", TransactionTraceParams.class);
final OpCodeTracerConfig emptyParamsConfig = emptyParams.traceOptions().opCodeTracerConfig();
// Passing {} should be equivalent to passing no options at all and therefore
// should produce the same behavior as TraceOptions.DEFAULT (including that
// memory tracing may be disabled by default).
final OpCodeTracerConfig defaultConfig = TraceOptions.DEFAULT.opCodeTracerConfig();
// Parse an empty JSON options object — simulates debug_traceTransaction(hash, {})
final TransactionTraceParams emptyParams = MAPPER.readValue("{}", TransactionTraceParams.class);
final OpCodeTracerConfig emptyParamsConfig = emptyParams.traceOptions().opCodeTracerConfig();

Copilot uses AI. Check for mistakes.
Comment on lines +57 to +60

assertThat(defaultConfig.traceStorage()).isTrue();
assertThat(defaultConfig.traceMemory()).isFalse();
assertThat(defaultConfig.traceStack()).isTrue();
Copy link

Copilot AI Feb 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test hard-codes the expected default booleans, which can make it brittle if OpCodeTracerConfig.DEFAULT changes. A more stable assertion would compare each field directly against OpCodeTracerConfig.DEFAULT (or assert object equality if supported), so the test continues to validate the relationship rather than specific constant values.

Suggested change
assertThat(defaultConfig.traceStorage()).isTrue();
assertThat(defaultConfig.traceMemory()).isFalse();
assertThat(defaultConfig.traceStack()).isTrue();
final OpCodeTracerConfig expectedConfig = OpCodeTracerConfig.DEFAULT;
assertThat(defaultConfig.traceStorage()).isEqualTo(expectedConfig.traceStorage());
assertThat(defaultConfig.traceMemory()).isEqualTo(expectedConfig.traceMemory());
assertThat(defaultConfig.traceStack()).isEqualTo(expectedConfig.traceStack());

Copilot uses AI. Check for mistakes.
Comment on lines +108 to +119
if (disableStorageNullable() != null) {
builder.traceStorage(!disableStorage());
}
if (disableMemoryNullable() != null) {
builder.traceMemory(!disableMemory());
} else if (tracerType != TracerType.OPCODE_TRACER) {
// Non-opcode tracers (e.g. callTracer) need memory capture enabled for internal
// operations such as extracting CREATE init code, even when disableMemory is not set
builder.traceMemory(true);
}
if (disableStackNullable() != null) {
builder.traceStack(!disableStack());
Copy link

Copilot AI Feb 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inside the *_Nullable() != null branches, consider using the nullable value you just checked (e.g., disableStorageNullable() / disableMemoryNullable()) rather than calling the separate boolean accessors again. This avoids any chance of diverging logic between the nullable and primitive getters and makes it clearer that you're applying only explicitly provided values.

Suggested change
if (disableStorageNullable() != null) {
builder.traceStorage(!disableStorage());
}
if (disableMemoryNullable() != null) {
builder.traceMemory(!disableMemory());
} else if (tracerType != TracerType.OPCODE_TRACER) {
// Non-opcode tracers (e.g. callTracer) need memory capture enabled for internal
// operations such as extracting CREATE init code, even when disableMemory is not set
builder.traceMemory(true);
}
if (disableStackNullable() != null) {
builder.traceStack(!disableStack());
final Boolean disableStorage = disableStorageNullable();
if (disableStorage != null) {
builder.traceStorage(!disableStorage);
}
final Boolean disableMemory = disableMemoryNullable();
if (disableMemory != null) {
builder.traceMemory(!disableMemory);
} else if (tracerType != TracerType.OPCODE_TRACER) {
// Non-opcode tracers (e.g. callTracer) need memory capture enabled for internal
// operations such as extracting CREATE init code, even when disableMemory is not set
builder.traceMemory(true);
}
final Boolean disableStack = disableStackNullable();
if (disableStack != null) {
builder.traceStack(!disableStack);

Copilot uses AI. Check for mistakes.
Comment on lines 653 to +656
"gas" : 292515,
"gasCost" : 6,
"depth" : 1,
"stack" : [ "0x9dc2c8f5", "0x227", "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", "0x1", "0x0", "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe9", "0x0" ],
"memory" : [ "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe9" ]
"stack" : [ "0x9dc2c8f5", "0x227", "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", "0x1", "0x0", "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe9", "0x0" ]
Copy link

Copilot AI Feb 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This fixture is named *_disableStorage.json but the updated expected output also reflects the default omission of memory (i.e., not just storage being disabled). To reduce confusion for future readers, consider renaming the fixture (or, if the test intent is strictly 'disableStorage only', adjust the underlying request in the fixture to explicitly set disableMemory: false so the name matches the behavior under test).

Copilot uses AI. Check for mistakes.
@macfarla macfarla merged commit 182c1a7 into hyperledger:main Feb 24, 2026
46 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

debug_traceTransaction default param behavior

3 participants